import React,{useRef,useState,useEffect} from "react";
import {Canvas,useLoader,useFrame} from "@react-three/fiber";
import {OrbitControls,useGLTF} from "@react-three/drei";
import {GLTFLoader} from 'three/examples/jsm/loaders/GLTFLoader';
import * as THREE from 'three';

//模型文件路径
const modelUrl='/public/models/titui.glb';
//动画文件路径数组
const animationUrls=['/public/models/lazy.glb','/public/models/song.glb','/public/models/zuizhong.glb'];
const ModelViewer:React.FC=()=>{
  const modelRef=useRef<THREE.Group>(null);
  const [mixer,setMixer]=useState<THREE.AnimationMixer | null>(null);
  const [actions,setActions]=useState<THREE.AnimationAction[]>([]);
  const [activeActionIndex,setActiveAcrionIndex]=useState(0);
  //加载模型
  const gltf=useLoader(GLTFLoader,modelUrl);
  //初始化动画混合器和动作
  useEffect(()=>{
    const loader=new GLTFLoader();
    const loadAnimations=async()=>{
      const animationClips=await Promise.all(
        animationUrls.map((url)=>{
           return new Promise<THREE.AnimationClip>((resolve,reject)=>{
            loader.load(url,(gltf)=>{
              if(gltf.animations.length>0){
                resolve(gltf.animations[0]);
              }
              else{
                reject(new Error(`No animations found in ${url}`));
              }
            },undefined,reject);
         
           })
        })
      );
      if(modelRef.current){
        const newMixer=new THREE.AnimationMixer(modelRef.current);
        const newActions=animationClips.map((clip)=>{
          const action=newMixer.clipAction(clip);
          action.enabled=true;
          action.setEffectiveTimeScale(1);
          action.setEffectiveWeight(0);
          return action;
        });
        //激活第一个动画
        newActions[0].setEffectiveWeight(1).play();
        setMixer(newMixer);
        setActions(newActions);
      }
    };
    loadAnimations();
  },[]);
  //更新动画
  useFrame((_,delta)=>{
    if(mixer){
      mixer.update(delta);
    }
  });
  //切换动画
  const switchAnimation=(index:number)=>{
    const currentAction=actions[activeActionIndex];
    const newAction=actions[index];
    if(currentAction!==newAction){
      newAction.reset().setEffectiveTimeScale(1).setEffectiveWeight(1).fadeIn(0.5);
      currentAction.fadeOut(0.5);
      setActiveAcrionIndex(index);
    }
  };
  return (
    <>
    <primitive ref={modelRef} object={gltf.scene} scale={1} position={[0,-1,0]}></primitive>
    <div style={{position:'absolute',top:"10px"}}>
         {
          actions.map((_,index)=>{
            <button>
              Animation{index+1}
            </button>
          })
         }
    </div>
    <OrbitControls/>
    </>
  )
};
const App:React.FC=()=>{
  return(
    <Canvas style={{width:'100vw',height:'100vh'}}>
        <ambientLight intensity={0.5}/>
        <directionalLight position={[1,1,1]} intensity={0.8}/>
        <ModelViewer/>
    </Canvas>
  )
};
export default App;
